/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef MSDP_SPATIAL_SLAVE_EPOCH_H
#define MSDP_SPATIAL_SLAVE_EPOCH_H

#include "spatial_awareness_epoch.h"

#include <map>
#include "spatial_master_epoch.h"

namespace OHOS {
namespace Msdp {
class SpatialSlaveEpoch : public SpatialAwarenessEpoch,
    public std::enable_shared_from_this<SpatialSlaveEpoch> {
public:
    SpatialSlaveEpoch(std::shared_ptr<SpatialMgrEventHandler> handler,
        std::shared_ptr<SpatialCommunicator> communicator,
        std::shared_ptr<SpatialCoordinateSystem> coordinateSystem)
        : SpatialAwarenessEpoch(handler, communicator, coordinateSystem)
        {
        }
    SpatialSlaveEpoch(std::shared_ptr<SpatialMasterEpoch> master);
    ~SpatialSlaveEpoch() = default;
    enum {
        EVENT_SLAVE_EPOCH_BASE = EVENT_EPOCH_INNER_BASE + 200,
        EVENT_SLAVE_EPOCH_LIFETIME_OUT,
    };
    void Start() override;
    uint32_t GetEpoch() override;
    bool HandleEvent(int32_t event, int64_t param) override;
private:
    static const int64_t SLAVE_EPOCH_LIFETIME = 10000;
    class SlaveListener : public SpatialCommunicator::SpatialSessionListener {
    public:
        SlaveListener(std::shared_ptr<SpatialSlaveEpoch> owner) : owner_(owner) {};
        ~SlaveListener() = default;
        virtual void OnSessionOpen(std::shared_ptr<SpatialCommunicator::Session> session) override;
        virtual void OnSessionClose(std::shared_ptr<SpatialCommunicator::Session> session) override;
        virtual void OnReceiveRequest(std::shared_ptr<SpatialCommunicator::Session> session,
            std::shared_ptr<SpatialRequest> request) override;
        virtual void OnReceiveResponse(std::shared_ptr<SpatialCommunicator::Session> session,
            std::shared_ptr<SpatialResponse> response) override;
    private:
        std::weak_ptr<SpatialSlaveEpoch> owner_;
    };
    friend class SlaveListener;
    void End() override;
    int64_t GetLifetime()
    {
        return SLAVE_EPOCH_LIFETIME;
    };

    void HandleGetMapRequest(std::shared_ptr<SpatialRequest> request);
    void HandleSyncMapOfferRequest(std::shared_ptr<SpatialRequest> request);
    void HandleSyncMapRequest(std::shared_ptr<SpatialRequest> request);
    void HandleDeviceState();
    void OnDeviceOnline(const DeviceInfo& device);
    void OnDeviceReady(const DeviceInfo& device);
    void OnDeviceOffline(const DeviceInfo& device);
    void OnDeviceChanged(const DeviceInfo& device);
    std::vector<DeviceInfo> foundDevices_;
    std::shared_ptr<SlaveListener> listener_;
    std::mutex syncLock_;
    SpatialMap ownMap_;
    bool exist_ {false};
};
} // namespace Msdp
} // namespace OHOS
#endif // MSDP_SPATIAL_SLAVE_EPOCH_H